#!/bin/bash
#
# Copyright 2015-2017 Adrian DC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# === ADB Strace Helper ===
function adbst()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbst <process_name> [parameters] [bool_wait] (strace)';
    echo '';
    return;
  fi;

  # Variables
  local cmd;
  local strace_exists;
  local target='/tmp';

  # Wait for the device
  adbwait 120;

  # Detect strace requirement
  strace_exists=$(adbsu 'if [ ! -e /system/bin/strace ]; then echo false; fi;');
  if [ ! -z "${strace_exists}" ]; then
    adbro;
    if [ ! -z "$(adbsu grep '64' /proc/cpuinfo)" ]; then
      adb push "${ANDROID_DEVELOPMENT_SHELL_TOOLS_FILES_STRACE_64}" "${target}/strace";
    else
      adb push "${ANDROID_DEVELOPMENT_SHELL_TOOLS_FILES_STRACE_32}" "${target}/strace";
    fi;
    adbsur "cp '${target}/strace' /system/bin/strace;
            rm '${target}/strace';
            chmod 777 /system/bin/strace";
    echo '';
  fi;

  # Process identifier command
  if [ -z "${3}" ]; then
    cmd="pid=\$(pgrep '${1}' | head -n1)";
  else
    cmd="echo 'adbst: Waiting for ${1}'; pid=''; while [ -z \"\${pid}\" ]; do pid=\$(pgrep '${1}' | head -n1); done";
  fi;

  # Append strace command
  cmd="${cmd}; if [ ! -z \"\${pid}\" ]; then /system/bin/strace -y ${2} -s 4096 -p \"\${pid}\"; else echo 'adbst: No matching process found...'; fi;";

  # Run command as root
  echo '';
  adbsu "${cmd}";
  echo '';
}

# === ADB Strace Followed Helper ===
function adbstf()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbstf <process_name> (Followed strace)';
    echo '';
    return;
  fi;

  # Use ADB Strace helper
  adbst "${1}" '-f';
}

# === ADB Strace Waiting Helper ===
function adbstw()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: adbstw <process_name> (Waiting strace)';
    echo '';
    return;
  fi;

  # Use ADB Strace helper
  adbst "${1}" '-f' 'true';
}

# === ADB Stack Tombstone Debugger ===
function adbstacktombstone()
{
  # Usage
  if stack -v > /dev/null 2>&1; then
    echo '';
    echo ' Usage: adbstacktombstone (ADB tombstone debugger with stack)';
    echo ' Information: "stack" has to be provided by AOSP envsetup';
    echo '';
    return;
  fi;

  # Variables
  local tombstone_last;

  # Acquire adb root access
  adbro;

  # Acquire last tombstone file
  tombstone_last=$(adb shell ls -t1 '/data/tombstones/tombstone*' \
                 | head -n 1);

  # Run slack wiht input
  stack <(adb shell cat "${tombstone_last}");
}
